﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using QUT.Gppg;
using ConceptsParser.SyntaxTree;

namespace Compiler.CompilerAPI
{
    public class ErrorHandler
    {
        private LinkedList<SemanticError> semanticErrors = new LinkedList<SemanticError>();
        private LinkedList<DebugInfo> debugMessages = new LinkedList<DebugInfo>();
        private LinkedList<Warning> warnings = new LinkedList<Warning>();

        public LinkedList<SemanticError> SemanticErrors
        {
            get { return semanticErrors; }
        }
        public LinkedList<Warning> Warnings
        {
            get { return warnings; }
        }

        public bool HasSemanticErrors
        {
            get { return semanticErrors.Count > 0; }
        }

        public LinkedList<DebugInfo> DebugMessages
        {
            get { return debugMessages; }
        }


        public ErrorHandler() { }

        public void AddSemanticError(SemanticError error)
        {
            if (error == null)
                throw new ArgumentNullException("error can not be null");
            semanticErrors.AddLast(error);
        }

        public void AddDebugMessage(DebugInfo message)
        {
            if (message == null)
                throw new ArgumentNullException("message can not be null");
            debugMessages.AddLast(message);
        }

        public void AddWarning(Warning warning)
        {
            if (warning == null)
                throw new ArgumentNullException("warning can not be null");
            warnings.AddLast(warning);
        }
    }

    public class SemanticError
    {
        private string errorMessage;
        private LexLocation location = null;

        public string ErrorMessage
        {
            get { return errorMessage; }
        }

        public SemanticError(string errorMessage)
        {
            if ((errorMessage == null) || (errorMessage == ""))
                throw new ArgumentOutOfRangeException("errorMessage can not be empty");
            this.errorMessage = errorMessage;
        }
        public SemanticError(string errorMessage, LexLocation location)
            : this(errorMessage)
        {
            this.location = location;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Семантическая ошибка. ");
            if (location != null)
                sb.Append(location.ToStringGood() + ": ");
            sb.Append(errorMessage);
            return sb.ToString();
        }
    }

    public class DebugInfo
    {
        private string message; 

        public DebugInfo(string message)
        {
            if ((message == null) || (message == ""))
                throw new ArgumentOutOfRangeException("message can not be empty");
            this.message = message;
        }

        public override string ToString()
        {
 	         return "Сообщение отладки. " + message + Environment.NewLine;
        }
    }

    public class Warning
    { 
        private string message;

        public Warning(string message)
        {
            if ((message == null) || (message == ""))
                throw new ArgumentOutOfRangeException("message can not be empty");
            this.message = message;
        }

        public override string ToString()
        {
 	         return "Предупреждение. " + message + Environment.NewLine;
        }
    }
}
